/************************************************************************
Copyright 2003, 2004, 2005, 2006, 2007, 2008 Grid Technology Research Center,
National Institute of Advanced Industrial Science and Technology.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************/

package jp.aist.gtrc.plus.scheduler.specific.sge.status;

import java.util.Collection;
import java.util.Map;

import jp.aist.gtrc.plus.scheduler.node.NodeResource;
import jp.aist.gtrc.plus.scheduler.specific.sge.jaxb.common.*;
import jp.aist.gtrc.plus.scheduler.status.ArchType;
import jp.aist.gtrc.plus.scheduler.status.JobStatus;
import jp.aist.gtrc.plus.scheduler.status.NodeStatus;
import jp.aist.gtrc.plus.scheduler.status.OSType;
import jp.aist.gtrc.plus.scheduler.status.QInstanceStatus;
import jp.aist.gtrc.plus.scheduler.util.HostUtil;
import jp.aist.gtrc.plus.scheduler.util.TextUtil;

public class SGEQInstance implements NodeStatus, QInstanceStatus {

	private final JAXBSGEQinstance qinstance;
	private int usedNumBias;
	private final String fullname;
	private SGENodeStatus node = null;

	private static final SGEStatusManager statusMgr = SGEStatusManager.getInstance();

	static final int QI_DEFAULT			= 0x00000000;
	static final int QI_SUSPENDED		= 0x00000100;
	static final int QI_ALARM			= 0x00000001;
	static final int QI_SUSPEND_ALARM	= 0x00000002;
	static final int QI_DISABLED		= 0x00000004;
	static final int QI_UNKNOWN			= 0x00000400;
	static final int QI_ERROR			= 0x00004000;
	static final int QI_SUSPENDED_ON_SUBORDINATE = 0x00008000;
	static final int QI_CAL_DISABLED	= 0x00020000;
	static final int QI_CAL_SUSPENDED	= 0x00040000;
	static final int QI_AMBIGUOUS		= 0x00080000;
	static final int QI_ORPHANED		= 0x00100000;
	static final int QI_FULL			= 0x00200000;

	public static final int getStateValue(String state) {

		if (TextUtil.isEmpty(state)) {
			return QI_DEFAULT;
		}

		int value = QI_DEFAULT;
		if (state.contains("s")) {
			value |= QI_SUSPENDED;
		}
		if (state.contains("au")) {
			value |= QI_UNKNOWN;
		}

		return value;

	}

	public SGEQInstance(JAXBSGEQinstance qinstance) {

		assert(qinstance != null);
		this.qinstance = qinstance;
		this.usedNumBias = 0;

		/*
		 * NOTE: getStatus("full_name") may be "all.q@host" or
		 * "all.q@host.example.com". Make FQDN style always.
		 */
		this.fullname = getQname() + "@" + getHostname();

	}

	public String getName() {

		/*
		 *	<QU_qhostname>host.example.com</QU_qhostname>
         *	<QU_qname>all.q</QU_qname>
         *	<QU_full_name>all.q@host.example.com</QU_full_name>
		 */
		return getFullName();

	}

	public String getQname() {

		return qinstance.getQUQname();

	}

	public String getHostname() {

		return HostUtil.makeFQDN(qinstance.getQUQhostname());

	}

	public String getFullName() {

		return fullname;

	}

	public int getTotalSlotNum() {

		return qinstance.getQUJobSlots();

	}

	public int getState() {

		return qinstance.getQUState();

	}

	public boolean isReadyToUse() {

		return (getState() == QI_DEFAULT);

	}

	public boolean isSuspended() {

		/*
		 * NOTE: We doesn't handle state=(SUSPENDED|UNKNWON) as suspended qins.
		 */
		return (getState() == QI_SUSPENDED);

	}

	public int getAllSlotNum() {

		return qinstance.getQUJobSlots();

	}

	public int getUsedSlotNum() {

		QUResourceUtilization util = qinstance.getQUResourceUtilization();

		if (util != null) {
			for (RUEElement e : util.getRUEElement()) {
				if (e.getRUEName().equals("slots")) {
					return (int)e.getRUEUtilizedNow() + usedNumBias;
				}
			}
		}

		return usedNumBias;

	}

	public void incrementUsedSlotNum(int nSlot) {

		usedNumBias += nSlot;

	}

	public int getVersion() {

		return qinstance.getQUVersion();

	}

	public void setNodeStatus(SGENodeStatus node) {

		this.node = node;

	}

	public NodeStatus getNode() {

		assert(node != null);
		return node;

	}

	public boolean isAlive() {

		return getNode().isAlive();

	}

	public boolean isIdle() {

		return (getUsedSlotNum() < getTotalSlotNum());

	}

	public OSType getOSType() {

		return getNode().getOSType();

	}

	public ArchType getArchType() {

		return getNode().getArchType();

	}

	public int getCPUNum() {

		//return getNode().getCPUNum();
		return getTotalSlotNum();

	}

	public double getLoadAverage() {

		return getNode().getLoadAverage();

	}

	public long getPhysicalMemory() {

		return getNode().getPhysicalMemory();

	}

	public int getRunningJobNum() {

		return getUsedSlotNum();

	}

	public NodeResource getResource() {

		return SGENodeResource.getInstance(node);

	}

	public String getAttribute(String attr) {

		return node.getAttribute(attr);

	}

	public Map<String, String> getAttributeMap() {

		return node.getAttributeMap();

	}

	public Collection<JobStatus> getJobs() {

		return statusMgr.getJobsOnQinstance(getFullName());

	}

}
